package br.ufc.great.dtxtester;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Vector;

import br.ufc.great.client.DTXResult;
import br.ufc.great.client.DTXTransaction;

public class ClientSimulator extends Thread {

	private DTXTester dtxTester;
	private DTXClient client;

	public ClientSimulator(DTXTester dtxTester, DTXClient client) {
		setPriority(Thread.MAX_PRIORITY);
		this.dtxTester = dtxTester;
		this.client = client;
	}
	
	public void run(){
		try {
			String clientTime = "";
			long clientInit = System.currentTimeMillis();
			int numberDeadlocks = 0;
			Vector<DTXTransaction> transactions = client.getTransactions();
			//boolean terminate = true;
			for (int i = 0; i < transactions.size(); i++) {
				//if (i == 0)
				//	terminate = true;
				DTXTransaction transaction = transactions.elementAt(i);
				Socket socket = new Socket(client.getSite().getHost(), client.getSite().getPort());
				ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
				long init = System.currentTimeMillis();
				output.writeObject(transaction);
				output.flush();
				ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
				DTXResult transactionResult = (DTXResult) input.readObject();
				long finish = System.currentTimeMillis();
				input.close();
				output.close();
				socket.close();
				String time = "";
				if ((finish - init) < 1000) {
					time += "0." + (finish - init) % 1000;
				}
				else {
					time += ((finish - init) / 1000) + "." + (finish - init) % 1000; 
				}
				if (transactionResult.getStatus() == DTXResult.ABORTED) {
					dtxTester.addLog(client.getName(), "Transaction " + transactionResult.getTransactionId() + " aborted in " + time + " seconds", true);
					numberDeadlocks++;
				}
				else {
					dtxTester.addLog(client.getName(), "Transaction " + transactionResult.getTransactionId() + " executed in " + time + " seconds", false);					
				}
				try {
					sleep(client.getTransactionsInterval());
				}
				catch (InterruptedException e) {
					dtxTester.addLog(e.getMessage(), true);
				}
				//if (transactionResult.getStatus() != DTXResult.COMMITED) {
					//i--;
					//continue;
					//terminate = false;
				//}
				//if (i == transactions.size() - 1 && terminate == false)
				//	i = -1;
			}
			long clientFinish = System.currentTimeMillis();
			if ((clientFinish - clientInit) < 1000) {
				clientTime += "0." + (clientFinish - clientInit) % 1000;
			}
			else {
				clientTime += ((clientFinish - clientInit) / 1000) + "." + (clientFinish - clientInit) % 1000; 
			}
			client.setExecutionTime(Double.parseDouble(clientTime));
			client.setNumberDeadlocks(numberDeadlocks);
			dtxTester.endClient(client);
		}
		catch (UnknownHostException e) {
			dtxTester.addLog(e.getMessage(), true);
		}
		catch (IOException e) {
			dtxTester.addLog(e.getMessage(), true);
		}
		catch (ClassNotFoundException e) {
			dtxTester.addLog(e.getMessage(), true);
		}
	}
	
}
